package be.android.forap.gui;

import java.io.File;
import java.io.IOException;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.ClipboardManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import be.android.forap.ForAp;
import be.android.forap.R;
import be.android.forap.crypto.PatternUtil;
import be.android.forap.crypto.CryptoUtil;
import be.android.forap.dataprovider.ContactManager;
import be.android.forap.dataprovider.ContactUtil;
import be.android.forap.dataprovider.RawContact;


public final class ContactAdder extends Activity{

	public static final String TAG = "ContactsAdder";

	private static final int SELECT_FILE = 1;

	public static final String ADD_PUBLICKEY_PATH = "addpublickeypath";
	public static final String ADD_PUBLICKEY_CONTACT = "addpublickey";
	public static final String EDIT_CONTACT = "editContact";
	public static final String CONTACT_GLOBALID = "globalname";
	public static final String CONTACT_FNAME = "fName";
	public static final String CONTACT_LNAME = "lname";
	public static final String CONTACT_PHONE = "phone";
	public static final String CONTACT_EMAIL = "emial";
	public static final String CONTACT_PUBKEY = "pubkey";

	private String selectedFilePath;
	/* public static final String ACCOUNT_NAME =
            "com.example.android.contactmanager.ContactsAdder.ACCOUNT_NAME";
    public static final String ACCOUNT_TYPE =
            "com.example.android.contactmanager.ContactsAdder.ACCOUNT_TYPE";*/

	private TextView mAccountName;
	private TextView mAccountTypeLabel;
	private ImageView mAccountIcon;

	private EditText mContactFirstNameEditText;
	private EditText mContactLastNameEditText;

	private EditText mContactEmailEditText;
	private EditText mContactPhoneEditText;

	private Button mImportKeyButton;
	private Button mContactSaveButton;
	private Button mContactCancelButton;

	private Account mAccount;

	private boolean mEdit;
	private boolean mAddPublicKey;

	private String mGlobalIdForEdit;

	/**
	 * Called when the activity is first created. Responsible for initializing the UI.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState){
		Log.v(TAG, "Activity State: onCreate()");
		super.onCreate(savedInstanceState);		
		setContentView(R.layout.contact_adder);
		setResult(RESULT_CANCELED, getIntent());

		Intent launcher = getIntent();
		mEdit  = launcher.getBooleanExtra(EDIT_CONTACT,false);
		mAddPublicKey = launcher.getBooleanExtra(ADD_PUBLICKEY_CONTACT, false);

		mAccountIcon = (ImageView) findViewById(R.id.addc_icon);

		mAccountName = (TextView) findViewById(R.id.addc_textview_accountName);
		mAccountTypeLabel = (TextView) findViewById(R.id.addc_textview_accountType);


		// Obtain handles to UI objects
		mContactFirstNameEditText = (EditText) findViewById(R.id.contactFirstNameEditText);
		mContactLastNameEditText = (EditText) findViewById(R.id.contactLastNameEditText);
		mContactPhoneEditText = (EditText) findViewById(R.id.contactPhoneEditText);
		mContactEmailEditText = (EditText) findViewById(R.id.contactEmailEditText);       

		mImportKeyButton = (Button) findViewById(R.id.addc_button_import_key);
		mContactSaveButton = (Button) findViewById(R.id.addc_button_save);		
		mContactCancelButton =  (Button) findViewById(R.id.addc_button_cancel);

		String pk = launcher.getStringExtra(CONTACT_PUBKEY);
		if(!TextUtils.isEmpty(pk)){
			publicKey = pk;
			if(!TextUtils.isEmpty(publicKey) && PatternUtil.matchPGPBlock(publicKey, PatternUtil.PGP_PUBLIC_KEY)){
				publicKeyIsValid = true;
				((TextView) findViewById(R.id.addc_textview_keyout)).setText("Selected public key is valid");
			} else {
				((TextView) findViewById(R.id.addc_textview_keyout)).setText("Error public key is empty or has illegal format");
			}
		}

		if(mEdit){
			mContactSaveButton.setText("Save changes");
			mGlobalIdForEdit= launcher.getStringExtra(CONTACT_GLOBALID);
			Log.d(TAG,"in add "+ mGlobalIdForEdit);
			if(TextUtils.isEmpty(mGlobalIdForEdit))
				finish();
		}

		if(mAddPublicKey){
			String pkPath = launcher.getStringExtra(ADD_PUBLICKEY_PATH);
			if(!TextUtils.isEmpty(pkPath)){
				try{
					publicKey = new String(CryptoUtil.getBytesFromFile(new File(pkPath)));
					if(!TextUtils.isEmpty(publicKey) && PatternUtil.matchPGPBlock(publicKey, PatternUtil.PGP_PUBLIC_KEY)){
						publicKeyIsValid = true;
						((TextView) findViewById(R.id.addc_textview_keyout)).setText("Selected public key from file");
					} else {
						((TextView) findViewById(R.id.addc_textview_keyout)).setText("Error public key is empty or has illegal format");
					}
				} catch (IOException e) {
					Toast.makeText(getApplicationContext(), "Import Error: " + e.toString(), Toast.LENGTH_LONG).show();
					e.printStackTrace();
				}
			}
		}


		String fn = launcher.getStringExtra(CONTACT_FNAME);
		String ln = launcher.getStringExtra(CONTACT_LNAME);
		String ph = launcher.getStringExtra(CONTACT_PHONE);
		String em = launcher.getStringExtra(CONTACT_EMAIL);

		if(!TextUtils.isEmpty(fn))
			mContactFirstNameEditText.setText(fn);
		if(!TextUtils.isEmpty(ln))
			mContactLastNameEditText.setText(ln);
		if(!TextUtils.isEmpty(ph))
			mContactPhoneEditText.setText(ph);
		if(!TextUtils.isEmpty(em))
			mContactEmailEditText.setText(em);




		mAccount = ForAp.getInstance().getForApAccount();
		AccountData aData = new AccountData(mAccount.name, getAuthenticatorDescription(mAccount.type,AccountManager.get(getApplicationContext()).getAuthenticatorTypes() ));
		mAccountIcon.setImageDrawable(aData.getIcon());
		mAccountName.setText(aData.getName());
		mAccountTypeLabel.setText(aData.getTypeLabel());
	}

	public void onClick(View v){
		switch (v.getId()) {
		case R.id.addc_button_import_key:
			importKey();
			break;
		case R.id.addc_button_copy_from_clipboard:
			copyKeyFromClipboard();
			break;
		case R.id.addc_button_gen_key:
			debugKey();
			break;
		case R.id.addc_button_save:
			saveContact();
			break;
		case R.id.addc_button_cancel:
			cancelAddContact();
			break;
		}
	}

	private boolean publicKeyIsValid = false;
	private String publicKey;

	private void importKey() {
		String[] formatFilter ={"asc","txt"};
		Intent selectFile = new Intent(this, FileExplorerActivity.class);
		selectFile.putExtra(FileExplorerActivity.START_PATH, "/sdcard/ForAp");
		selectFile.putExtra(FileExplorerActivity.FORMAT_FILTER,formatFilter);
		selectFile.putExtra(FileExplorerActivity.SELECT_ONLY_FILE_READ, true);
		startActivityForResult(selectFile, SELECT_FILE);

	}

	private void copyKeyFromClipboard() {
		ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
		publicKey = clipboard.getText().toString();
		if(!TextUtils.isEmpty(publicKey) && PatternUtil.matchPGPBlock(publicKey, PatternUtil.PGP_PUBLIC_KEY)){
			publicKeyIsValid = true;
			((TextView) findViewById(R.id.addc_textview_keyout)).setText("Selected public key from clipboard");
		} else {
			((TextView) findViewById(R.id.addc_textview_keyout)).setText("Error public key is empty or has illegal format");
		}

	}



	private void debugKey() {
		publicKey = ForAp.getInstance().getPublicKey();
		if(!TextUtils.isEmpty(publicKey) && PatternUtil.matchPGPBlock(publicKey, PatternUtil.PGP_PUBLIC_KEY)){
			publicKeyIsValid = true;
			((TextView) findViewById(R.id.addc_textview_keyout)).setText("Selected public key is own key (for debug use)");
		} else {
			((TextView) findViewById(R.id.addc_textview_keyout)).setText("Error public key is empty or has illegal format");
		}
	}


	/**
	 * Actions for when the Save button is clicked. Creates a contact entry and terminates the
	 * activity.
	 */
	private void saveContact() {
		try{
			String fname;
			String lname;
			String phone;
			String email;
			fname = mContactFirstNameEditText.getText().toString();
			lname = mContactLastNameEditText.getText().toString();
			phone = mContactPhoneEditText.getText().toString();
			email = mContactEmailEditText.getText().toString();
			if(TextUtils.isEmpty(fname) && TextUtils.isEmpty(lname)){
				Toast.makeText(getApplicationContext(), "Error no name was given!", Toast.LENGTH_SHORT).show();
				return;				
			}
			if(TextUtils.isEmpty(phone) && TextUtils.isEmpty(email)){
				Toast.makeText(getApplicationContext(), "Error no phone or email was given!", Toast.LENGTH_SHORT).show();
				return;
			}

			if(!publicKeyIsValid){
				Toast.makeText(getApplicationContext(), "Error no public key file was selected!", Toast.LENGTH_SHORT).show();
				return;
			}
			if(mEdit){
				RawContact updated = RawContact.createNewContact("", fname, lname, phone, email, publicKey, mGlobalIdForEdit);
				ContactManager.updateContact(this, mGlobalIdForEdit, updated);
				setResult(RESULT_OK, getIntent());
			}else{
				String globalID = ContactUtil.generateUniqueGlobalID();
				RawContact newContact = RawContact.createNewContact("", fname, lname, phone, email, publicKey, globalID);
				ContactManager.addNewContact(this, mAccount.name, newContact);
				setResult(RESULT_OK, getIntent());
			}			
			finish();
		}catch (Exception e) {
			Toast.makeText(getApplicationContext(), "Encrypt Error: " + e.toString(), Toast.LENGTH_LONG).show();
		}

	}


	private void cancelAddContact() {
		finish();
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == SELECT_FILE) {
			if (resultCode == Activity.RESULT_OK) {				 
				selectedFilePath = data.getStringExtra(FileExplorerActivity.RESULT_PATH);
				Toast.makeText(this,"Selected file: "+ selectedFilePath,Toast.LENGTH_LONG).show();
				try {
					publicKey = new String(CryptoUtil.getBytesFromFile(new File(selectedFilePath)));
					if(!TextUtils.isEmpty(publicKey) && PatternUtil.matchPGPBlock(publicKey, PatternUtil.PGP_PUBLIC_KEY)){
						publicKeyIsValid = true;
						((TextView) findViewById(R.id.addc_textview_keyout)).setText("Selected public key from file");
					} else {
						((TextView) findViewById(R.id.addc_textview_keyout)).setText("Error public key is empty or has illegal format");
					}
				} catch (IOException e) {
					Toast.makeText(getApplicationContext(), "Import Error: " + e.toString(), Toast.LENGTH_LONG).show();
					e.printStackTrace();
				}
			} else if (resultCode == Activity.RESULT_CANCELED) {
				((TextView) findViewById(R.id.addc_textview_keyout)).setText("Selected file: "+ "Error selecting a file");
			}
		}
	}



	/**
	 * Obtain the AuthenticatorDescription for a given account type.
	 * @param type The account type to locate.
	 * @param dictionary An array of AuthenticatorDescriptions, as returned by AccountManager.
	 * @return The description for the specified account type.
	 */
	private static AuthenticatorDescription getAuthenticatorDescription(String type,
			AuthenticatorDescription[] dictionary) {
		for (int i = 0; i < dictionary.length; i++) {
			if (dictionary[i].type.equals(type)) {
				return dictionary[i];
			}
		}
		// No match found
		throw new RuntimeException("Unable to find matching authenticator");
	}



	/**
	 * A container class used to repreresent all known information about an account.
	 */
	private class AccountData {
		private String mName;
		private String mType;
		private CharSequence mTypeLabel;
		private Drawable mIcon;

		/**
		 * @param name The name of the account. This is usually the user's email address or
		 *        username.
		 * @param description The description for this account. This will be dictated by the
		 *        type of account returned, and can be obtained from the system AccountManager.
		 */
		public AccountData(String name, AuthenticatorDescription description) {
			mName = name;
			if (description != null) {
				mType = description.type;

				// The type string is stored in a resource, so we need to convert it into something
				// human readable.
				String packageName = description.packageName;
				PackageManager pm = getPackageManager();

				if (description.labelId != 0) {
					mTypeLabel = pm.getText(packageName, description.labelId, null);
					if (mTypeLabel == null) {
						throw new IllegalArgumentException("LabelID provided, but label not found");
					}
				} else {
					mTypeLabel = "";
				}

				if (description.iconId != 0) {
					mIcon = pm.getDrawable(packageName, description.iconId, null);
					if (mIcon == null) {
						throw new IllegalArgumentException("IconID provided, but drawable not " +
								"found");
					}
				} else {
					mIcon = getResources().getDrawable(android.R.drawable.sym_def_app_icon);
				}
			}
		}

		public String getName() {
			return mName;
		}

		public String getType() {
			return mType;
		}

		public CharSequence getTypeLabel() {
			return mTypeLabel;
		}

		public Drawable getIcon() {
			return mIcon;
		}

		public String toString() {
			return mName;
		}
	}


}